<template>
  {{ jsonData }}
  <hr />
  <!-- {{ jsonDataBakup }} -->

  <ElForm label-position="top">
    <div style="margin: 0 10px">
      <ElRow>
        <template v-for="(item, index) in jsonDataField" :key="index">
          <ElCol :span="12" :xs="24" :sm="24" :md="12" style="padding: 0 10px; box-sizing: border-box">
            <!-- 文本框 -->
            <template v-if="item.itemType == 'text'">
              <ElFormItem :label="item.filedName">
                <!-- prettier-ignore -->
                <ElInput v-model="(jsonData[item.filedName] as string)" clearable
                  :disabled="item.filedName.toLowerCase() == 'xmbh' || item.filedName.toLowerCase() == '项目编号'">
                  <template #append v-if="item.append">
                    {{ item.append }}
                  </template>
                </ElInput>
              </ElFormItem>
            </template>
            <!-- 下拉框 -->
            <template v-else-if="item.itemType == 'select'">
              <ElFormItem :label="item.filedName">
                <ElSelect v-model="jsonData[item.filedName]" placeholder="请下拉选择" style="width: 100%">
                  <ElOption v-for="(option, index) in jsonDataBakup[item.filedName]" :key="index" :label="option"
                    :value="option" />
                </ElSelect>
              </ElFormItem>
            </template>
            <!-- 复选框 -->
            <template v-else-if="item.itemType == 'checkbox'">
              <ElFormItem :label="item.filedName">
                <div style="width: 100%">
                  <template
                    v-for="(option, index) in Object.keys((jsonDataBakup[item.filedName] as Array<IFormData>)[0])"
                    :key="index">
                    <div v-if="option.indexOf('_chk') > -1">
                      <ElCheckbox v-model="((jsonData[item.filedName] as Array<IFormData>)[0][option] as string)"
                        :label="option.replace('_chk', '')" />
                    </div>
                    <div v-else>
                      <div class="flex gap-4 mb-4">
                        <ElText>{{ option }}</ElText>
                        <ElInput v-model="((jsonData[item.filedName] as Array<IFormData>)[0][option] as string)"
                          clearable placeholder="请输入到文本框" />
                      </div>
                    </div>
                  </template>
                </div>
              </ElFormItem>
            </template>
            <!-- 日期时间 -->
            <template v-else-if="item.itemType == 'datetime'">
              <ElFormItem :label="item.filedName">
                <!-- prettier-ignore -->
                <ElDatePicker v-model="(jsonData[item.filedName] as string)" type="datetime" placeholder="选择日期和时间"
                  format="YYYY/MM/DD HH:mm:ss" value-format="YYYY/MM/DD HH:mm:ss" style="width: 100%" />
              </ElFormItem>
            </template>
            <!-- 动态表格 -->
            <template v-else-if="item.itemType == 'table'">
              <ElFormItem :label="item.filedName">
                <div style="
                    border: 1px solid rgb(225, 228, 233);
                    width: 100%;
                    overflow: auto;
                    border-radius: 5px;
                  ">
                  <!-- prettier-ignore -->
                  <EditTable :table-data="(jsonData[item.filedName] as Array<object>)" />
                </div>
              </ElFormItem>
            </template>

            <template v-else>
              <ElFormItem :label="'异常表单项: ' + item.filedName">
                <ElText>数据转化异常</ElText>
              </ElFormItem>
            </template>
          </ElCol>
        </template>
      </ElRow>
      <div style="padding: 0 10px">
        <ElFormItem label=" ">
          <ElButton type="primary" @click="submit">提交</ElButton>
          <ElButton link @click="reset">重置</ElButton>
        </ElFormItem>
      </div>
    </div>
  </ElForm>
</template>

<script setup lang="ts">
import type { IFormData } from './commonType'
import { ref, watch } from 'vue'
import EditTable from '@/components/EditTable/EditTable.vue'

const jsonData = ref<IFormData>({})
const jsonDataBakup = ref<IFormData>({})

const props = defineProps<{
  formData?: IFormData
}>()

type IFiledDicts = {
  filedName: string
  itemType: string
  append?: string
}

/**
 * 生成字段字典
 * @returns
 */
const generateFiledDicts = () => {
  const fileds = Object.keys(jsonDataBakup.value)

  const newFileds: { filedName: string; itemType: string }[] = []

  // 遍历字段字典，如果字段存在于jsonData中，则使用jsonData中的itemType，否则使用默认值
  fileds.forEach((filed) => {
    // 渲染规则
    //  checkbox, 如果字段的值是数组，且数组元素是对象，且对象的字段至少有一个包含_chk，那么就渲染checkbox，否则渲染text
    //  动态表格, 如果字段的值是数组，且数组元素是对象，且对象的字段有多个，那么就渲染动态表格

    const value = jsonData.value[filed]
    // console.log('value', value)
    // 1. 判断字段的值是否是数组
    if (Array.isArray(value)) {
      const valueArr = value as Array<object>
      // 1-1. 判断字段的值是否是对象
      if (typeof valueArr[0] === 'object') {
        // 1-2. 判断字段的值是否是对象的字段至少有一个包含_chk
        if (Object.keys(valueArr[0]).findIndex((m) => m.indexOf('_chk') > -1) > -1) {
          newFileds.push({
            filedName: filed,
            itemType: 'checkbox',
          })
        }
        // 1-3. 判断字段的值是否是对象的字段有多个
        else if (Object.keys(valueArr[0]).length > 1) {
          newFileds.push({
            filedName: filed,
            itemType: 'table',
          })
        } else {
          console.log(filed)
          throw new Error('字段的值 校验异常, 非表格/复选框')
        }
      } else {
        throw new Error('字段的值 校验异常, 非表格/复选框')
      }
    }
    // 2. 判断字段的值是否是字符串
    else if (typeof value === 'string') {
      // 值
      const valueStr = value?.toString().trim()

      const obj: IFiledDicts = {
        filedName: filed,
        itemType: 'text',
      }

      // 判断 字段 名 是否包含 (时间/日期), 如果包含 时间, 则显示 时间选择框, 否则显示 文本框
      if (filed.indexOf('时间') > -1) {
        obj.itemType = 'datetime'
      }

      // 判断 字段 名 是否 不是项目编号, 且包含值, 则将值作为 后缀 显示, 否则显示 文本框, 且清空值
      if (valueStr && valueStr.length > 0 && filed != '项目编号' && filed.toLowerCase() != 'xmbh') {
        // 如果值 存在则 赋值后缀, 并清空值, 防止显示时的值为 后缀
        obj.append = jsonData.value[filed].toString()
        jsonData.value[filed] = ''
      }

      newFileds.push(obj)
    }
    // 3. 判断字段的值是否是对象
    else if (typeof jsonData.value[filed] === 'object') {
      throw new Error('字段的值 校验异常, Object')
    }
    // 4. 如果不是以上类型, 则抛出异常
    else {
      console.log('value', value)
      throw new Error('字段的值 校验异常')
    }
  })

  return newFileds as Array<IFiledDicts>
}

// 表单字段, 初始化
const jsonDataField = ref<Array<IFiledDicts>>()
jsonDataField.value = generateFiledDicts()

/**
 * 深拷贝
 * @param data
 * @returns
 */
const deepClone = (data: IFormData) => {
  return JSON.parse(JSON.stringify(data))
}

/**
 * 初始化表单数据(将表单初始化内容进行封装)
 * @param data
 */
const initFormData = (data: IFormData) => {
  jsonData.value = deepClone(data)
  jsonDataBakup.value = deepClone(data)
  jsonDataField.value = generateFiledDicts()
}

// 监听 formData 的值, 如果 formData 存在, 则使用 formData 的值 重置 jsonData 和 jsonDataBakup
watch(
  () => props.formData,
  (newVal) => {
    // 如果 newVal 存在, 则使用 newVal 的值 重置 jsonData 和 jsonDataBakup
    if (newVal && Object.keys(newVal).length > 0) {
      initFormData(newVal!)
    }
  },
  {
    immediate: true,
    deep: true,
  },
)

const emit = defineEmits<{
  (e: 'submit', data: IFormData): void
}>()

const submit = () => {
  emit('submit', deepClone(jsonData.value))
}

const reset = () => {
  // 重置操作, 使用 jsonDataBakup 的值 重置 jsonData 的值
  initFormData(jsonDataBakup.value)
}
</script>

<style scoped>
:root {
  .el-form {
    --el-form-label-font-size: 20px;
    --el-form-label-font-weight: 500;
  }
}

:deep(.el-form-item--label-top .el-form-item__label) {
  font-weight: var(--el-form-label-font-weight);
}

/* 小屏幕手机端 */
@media (min-width: 0px) and (max-width: 768px) {}

/* 中等屏幕（桌面显示器，大于等于 992px） */
@media (min-width: 768px) and (max-width: 992px) {}

/* 大屏幕（大桌面显示器，大于等于 1200px） */
@media (min-width: 992px) {}
</style>
